﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
using Windows.Graphics.Imaging;
using Windows.Storage;
using Windows.Storage.Streams;

namespace DNFImagePacks2Manager.Helpers
{
    public enum InterpolationMode
    {
        [Description("最近邻插值 - 快速拉伸，画质粗糙")]
        NearestNeighbor = 0,
        [Description("双线性插值 - 平滑拉伸，中等画质")]
        Bilinear = 1,
        [Description("双三次插值 - 高质量拉伸，细节均衡")]
        Bicubic = 2,
        [Description("Lanczos插值 - 高锐度保留，抗锯齿优")]
        Lanczos = 3,
    }

    public enum FillStrategy { Repeat, Loop, Slow }

    public class ImageHelper
    {
        private static readonly Dictionary<InterpolationMode, Action<byte[], int, int, byte[], int, int>> _interpolationMethods =
            new()
            {
                { InterpolationMode.NearestNeighbor, StretchPixelsNearestNeighbor },
                { InterpolationMode.Bilinear, StretchPixelsBilinear },
                { InterpolationMode.Bicubic, StretchPixelsBicubic },
                { InterpolationMode.Lanczos, StretchPixelsLanczos },
            };

        public static SoftwareBitmap? ConvertBitmapToSoftwareBitmap(byte[] pixelData, int width, int height, int type = 0x10)
        {
            byte[]? bgraData = null;
            switch (type)
            {
                case 0x10:
                    bgraData = pixelData;
                    break;
                case 0x0F:
                    bgraData = ConvertArgb4444ToBgra8(pixelData, width, height);
                    break;
                case 0x0E:
                    bgraData = ConvertArgb1555ToBgra8(pixelData, width, height);
                    break;
            }

            if (bgraData == null)
            {
                return null;
            }

            try
            {
                SoftwareBitmap softwareBitmap = new(
                    BitmapPixelFormat.Bgra8,
                    width,
                    height,
                    BitmapAlphaMode.Premultiplied
                );
                softwareBitmap.CopyFromBuffer(bgraData.AsBuffer());

                return softwareBitmap;
            }
            catch (Exception)
            {
                return null;
            }
        }

        public static SoftwareBitmap? CreateTransparentSoftwareBitmap(int width, int height)
        {
            try
            {

                SoftwareBitmap softwareBitmap = new(
                    BitmapPixelFormat.Bgra8,
                    width,
                    height,
                    BitmapAlphaMode.Premultiplied
                );

                return softwareBitmap;
            }
            catch (Exception)
            {
                return null;
            }
        }

        public static async Task<SoftwareBitmap?> ConvertImageToSoftwareBitmap(string filePath)
        {
            try
            {
                StorageFile file = await StorageFile.GetFileFromPathAsync(filePath);
                return await ConvertImageToSoftwareBitmap(file);
            }
            catch (Exception)
            {
                return null;
            }
        }

        public static async Task<SoftwareBitmap?> ConvertImageToSoftwareBitmap(StorageFile file)
        {
            try
            {
                using IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.Read);
                BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream);

                SoftwareBitmap softwareBitmap = await decoder.GetSoftwareBitmapAsync(
                    BitmapPixelFormat.Bgra8,
                    BitmapAlphaMode.Premultiplied
                );

                return softwareBitmap;
            }
            catch (Exception)
            {
                return null;
            }
        }

        public static byte[]? ConvertSoftwareBitmapToPixelBytesAsync(SoftwareBitmap softwareBitmap, out int width, out int height)
        {
            width = 0;
            height = 0;
            if (softwareBitmap == null)
                return null;

            try
            {
                SoftwareBitmap bgraBitmap = softwareBitmap.BitmapPixelFormat == BitmapPixelFormat.Bgra8
                    ? softwareBitmap
                    : SoftwareBitmap.Convert(softwareBitmap, BitmapPixelFormat.Bgra8, softwareBitmap.BitmapAlphaMode);

                width = bgraBitmap.PixelWidth;
                height = bgraBitmap.PixelHeight;
                int pixelCount = width * height * 4;
                byte[] pixelBytes = new byte[pixelCount];

                var buffer = pixelBytes.AsBuffer();
                bgraBitmap.CopyToBuffer(buffer);

                return pixelBytes;
            }
            catch (Exception)
            {
                return null;
            }
        }

        private static byte[] ConvertArgb4444ToBgra8(byte[] argb4444Data, int width, int height)
        {
            int pixelCount = width * height;
            byte[] bgra8Data = new byte[pixelCount * 4];

            for (int i = 0; i < pixelCount; i++)
            {
                ushort pixel = BitConverter.ToUInt16(argb4444Data, i * 2);

                byte a = (byte)(pixel >> 12 & 0x0F);
                byte r = (byte)(pixel >> 8 & 0x0F);
                byte g = (byte)(pixel >> 4 & 0x0F);
                byte b = (byte)(pixel & 0x0F);

                a = (byte)(a << 4 | a);
                r = (byte)(r << 4 | r);
                g = (byte)(g << 4 | g);
                b = (byte)(b << 4 | b);

                int destIndex = i * 4;
                bgra8Data[destIndex + 0] = b;
                bgra8Data[destIndex + 1] = g;
                bgra8Data[destIndex + 2] = r;
                bgra8Data[destIndex + 3] = a;
            }
            return bgra8Data;
        }

        private static byte[] ConvertArgb1555ToBgra8(byte[] argb1555Data, int width, int height)
        {
            int pixelCount = width * height;
            byte[] bgra8Data = new byte[pixelCount * 4];

            for (int i = 0; i < pixelCount; i++)
            {
                ushort pixel = BitConverter.ToUInt16(argb1555Data, i * 2);

                byte a = (byte)(pixel >> 15 & 0x01);
                byte r = (byte)(pixel >> 10 & 0x1F);
                byte g = (byte)(pixel >> 5 & 0x1F);
                byte b = (byte)(pixel & 0x1F);

                a = (byte)(a * 255);
                r = (byte)(r << 3 | r >> 2);
                g = (byte)(g << 3 | g >> 2);
                b = (byte)(b << 3 | b >> 2);

                int destIndex = i * 4;
                bgra8Data[destIndex + 0] = b;
                bgra8Data[destIndex + 1] = g;
                bgra8Data[destIndex + 2] = r;
                bgra8Data[destIndex + 3] = a;
            }
            return bgra8Data;
        }

        private static byte[] ConvertArgb8888ToBgra8(byte[] argb8888Data)
        {
            byte[] bgra8Data = new byte[argb8888Data.Length];
            for (int i = 0; i < argb8888Data.Length; i += 4)
            {
                byte a = argb8888Data[i + 0];
                byte r = argb8888Data[i + 1];
                byte g = argb8888Data[i + 2];
                byte b = argb8888Data[i + 3];

                bgra8Data[i + 0] = b;
                bgra8Data[i + 1] = g;
                bgra8Data[i + 2] = r;
                bgra8Data[i + 3] = a;
            }
            return bgra8Data;
        }

        // 图像缩放算法
        public static void StretchPixelsOptimized(
            byte[] sourcePixels, int sourceWidth, int sourceHeight,
            byte[] destPixels, int destWidth, int destHeight,
            bool guassianBlur = true,
            InterpolationMode mode = InterpolationMode.Bicubic)
        {
            // 1. 参数验证
            ValidateParameters(sourcePixels, sourceWidth, sourceHeight, destPixels, destWidth, destHeight);

            // 2. 源图像或目标图像为1x1时，直接处理
            if (sourceWidth == 1 && sourceHeight == 1)
            {
                StretchSinglePixel(sourcePixels, destPixels, destWidth, destHeight);
                return;
            }
            if (destWidth == 1 && destHeight == 1)
            {
                StretchToSinglePixel(sourcePixels, sourceWidth, sourceHeight, destPixels, mode);
                return;
            }

            // 3. 高斯模糊预处理
            byte[] processedPixels = sourcePixels;
            if (guassianBlur)
            {
                // 计算缩放比例
                float scaleX = (float)destWidth / sourceWidth;
                float scaleY = (float)destHeight / sourceHeight;
                bool isDownscale = scaleX < 0.5f || scaleY < 0.5f;

                // 仅对有效降采样（非极小图像）应用模糊
                if (isDownscale && sourceWidth > 1 && sourceHeight > 1)
                {
                    float sigma = 0.5f / Math.Min(scaleX, scaleY);
                    processedPixels = GaussianBlur(sourcePixels, sourceWidth, sourceHeight, sigma);
                }
            }

            // 4. 执行缩放
            if (!_interpolationMethods.TryGetValue(mode, out var interpolationMethod))
            {
                throw new ArgumentOutOfRangeException(nameof(mode), "不支持的插值算法");
            }
            interpolationMethod(processedPixels, sourceWidth, sourceHeight, destPixels, destWidth, destHeight);
        }

        // 直接调用插值方法
        public static void StretchPixels(
            byte[] sourcePixels, int sourceWidth, int sourceHeight,
            byte[] destPixels, int destWidth, int destHeight,
            InterpolationMode mode)
        {
            ValidateParameters(sourcePixels, sourceWidth, sourceHeight, destPixels, destWidth, destHeight);
            if (!_interpolationMethods.TryGetValue(mode, out var interpolationMethod))
            {
                throw new ArgumentOutOfRangeException(nameof(mode), "不支持的插值算法");
            }
            interpolationMethod(sourcePixels, sourceWidth, sourceHeight, destPixels, destWidth, destHeight);
        }

        // 参数验证：检查输入有效性
        private static void ValidateParameters(
            byte[] sourcePixels, int sourceWidth, int sourceHeight,
            byte[] destPixels, int destWidth, int destHeight)
        {
            if (sourcePixels == null) throw new ArgumentNullException(nameof(sourcePixels));
            if (destPixels == null) throw new ArgumentNullException(nameof(destPixels));
            if (sourceWidth <= 0) throw new ArgumentOutOfRangeException(nameof(sourceWidth), "源宽度必须大于0");
            if (sourceHeight <= 0) throw new ArgumentOutOfRangeException(nameof(sourceHeight), "源高度必须大于0");
            if (destWidth <= 0) throw new ArgumentOutOfRangeException(nameof(destWidth), "目标宽度必须大于0");
            if (destHeight <= 0) throw new ArgumentOutOfRangeException(nameof(destHeight), "目标高度必须大于0");

            int expectedSourceLength = sourceWidth * sourceHeight * 4;
            if (sourcePixels.Length != expectedSourceLength)
            {
                throw new ArgumentException($"源像素数组长度无效（预期：{expectedSourceLength}，实际：{sourcePixels.Length}）", nameof(sourcePixels));
            }
            int expectedDestLength = destWidth * destHeight * 4;
            if (destPixels.Length != expectedDestLength)
            {
                throw new ArgumentException($"目标像素数组长度无效（预期：{expectedDestLength}，实际：{destPixels.Length}）", nameof(destPixels));
            }
        }

        // 源图像为1x1时，直接填充目标图像
        private static void StretchSinglePixel(byte[] sourcePixels, byte[] destPixels, int destWidth, int destHeight)
        {
            byte b = sourcePixels[0];
            byte g = sourcePixels[1];
            byte r = sourcePixels[2];
            byte a = sourcePixels[3];
            int destLength = destWidth * destHeight * 4;
            for (int i = 0; i < destLength; i += 4)
            {
                destPixels[i] = b;
                destPixels[i + 1] = g;
                destPixels[i + 2] = r;
                destPixels[i + 3] = a;
            }
        }

        // 目标图像为1x1时，用对应插值算法计算单个像素
        private static void StretchToSinglePixel(
            byte[] sourcePixels, int sourceWidth, int sourceHeight,
            byte[] destPixels, InterpolationMode mode)
        {
            byte[] tempDest = new byte[4];
            StretchPixels(sourcePixels, sourceWidth, sourceHeight, tempDest, 1, 1, mode);

            destPixels[0] = tempDest[0];
            destPixels[1] = tempDest[1];
            destPixels[2] = tempDest[2];
            destPixels[3] = tempDest[3];
        }

        // 最近邻插值算法：快速拉伸像素（速度优先，画质一般）
        private static void StretchPixelsNearestNeighbor(
            byte[] sourcePixels, int sourceWidth, int sourceHeight,
            byte[] destPixels, int destWidth, int destHeight)
        {
            if (sourceWidth <= 0 || sourceHeight <= 0 || destWidth <= 0 || destHeight <= 0)
                return;

            if (sourceWidth == 1 && sourceHeight == 1)
            {
                byte b = sourcePixels[0];
                byte g = sourcePixels[1];
                byte r = sourcePixels[2];
                byte a = sourcePixels[3];
                Parallel.For(0, destHeight, dy =>
                {
                    int destRowStart = dy * destWidth * 4;
                    for (int dx = 0; dx < destWidth; dx++)
                    {
                        int destIdx = destRowStart + dx * 4;
                        destPixels[destIdx] = b;
                        destPixels[destIdx + 1] = g;
                        destPixels[destIdx + 2] = r;
                        destPixels[destIdx + 3] = a;
                    }
                });
                return;
            }

            float xRatio = (float)sourceWidth / destWidth;
            float yRatio = (float)sourceHeight / destHeight;

            int sourceRowStride = sourceWidth * 4;
            int destRowStride = destWidth * 4;

            Parallel.For(0, destHeight, dy =>
            {
                float srcY = dy * yRatio;
                int srcYInt = (int)(srcY + 0.5f);

                if (srcYInt < 0) srcYInt = 0;
                else if (srcYInt >= sourceHeight) srcYInt = sourceHeight - 1;

                int sourceRowStart = srcYInt * sourceRowStride;
                int destRowStart = dy * destRowStride;

                for (int dx = 0; dx < destWidth; dx++)
                {
                    float srcX = dx * xRatio;
                    int srcXInt = (int)(srcX + 0.5f);

                    if (srcXInt < 0) srcXInt = 0;
                    else if (srcXInt >= sourceWidth) srcXInt = sourceWidth - 1;

                    int sourceIdx = sourceRowStart + srcXInt * 4;
                    int destIdx = destRowStart + dx * 4;

                    destPixels[destIdx] = sourcePixels[sourceIdx];
                    destPixels[destIdx + 1] = sourcePixels[sourceIdx + 1];
                    destPixels[destIdx + 2] = sourcePixels[sourceIdx + 2];
                    destPixels[destIdx + 3] = sourcePixels[sourceIdx + 3];
                }
            });
        }

        // 双线性插值算法：平滑拉伸像素（速度中等，画质较好）
        private static void StretchPixelsBilinear(
            byte[] sourcePixels, int sourceWidth, int sourceHeight,
            byte[] destPixels, int destWidth, int destHeight)
        {
            if (sourceWidth <= 1 || sourceHeight <= 1 || destWidth <= 0 || destHeight <= 0)
            {
                if (sourcePixels.Length > 0 && destPixels.Length > 0)
                {
                    byte b = sourcePixels[0];
                    byte g = sourcePixels[1];
                    byte r = sourcePixels[2];
                    byte a = sourcePixels[3];
                    Parallel.For(0, destHeight, dy =>
                    {
                        int rowStart = dy * destWidth * 4;
                        for (int dx = 0; dx < destWidth; dx++)
                        {
                            int idx = rowStart + dx * 4;
                            destPixels[idx] = b;
                            destPixels[idx + 1] = g;
                            destPixels[idx + 2] = r;
                            destPixels[idx + 3] = a;
                        }
                    });
                }
                return;
            }

            float xRatio = (float)(sourceWidth - 1) / destWidth;
            float yRatio = (float)(sourceHeight - 1) / destHeight;

            int sourceRowStride = sourceWidth * 4;
            int destRowStride = destWidth * 4;

            Parallel.For(0, destHeight, dy =>
            {
                float srcY = dy * yRatio;
                int y0 = (int)Math.Floor(srcY);
                int y1 = y0 + 1;
                float v = srcY - y0;
                float oneMinusV = 1 - v;

                if (y0 < 0) y0 = 0;
                else if (y0 >= sourceHeight) y0 = sourceHeight - 1;
                if (y1 < 0) y1 = 0;
                else if (y1 >= sourceHeight) y1 = sourceHeight - 1;

                int sourceY0Start = y0 * sourceRowStride;
                int sourceY1Start = y1 * sourceRowStride;

                int destRowStart = dy * destRowStride;

                for (int dx = 0; dx < destWidth; dx++)
                {
                    float srcX = dx * xRatio;
                    int x0 = (int)Math.Floor(srcX);
                    int x1 = x0 + 1;
                    float u = srcX - x0;
                    float oneMinusU = 1 - u;

                    if (x0 < 0) x0 = 0;
                    else if (x0 >= sourceWidth) x0 = sourceWidth - 1;
                    if (x1 < 0) x1 = 0;
                    else if (x1 >= sourceWidth) x1 = sourceWidth - 1;

                    int idx00 = sourceY0Start + x0 * 4;
                    int idx10 = sourceY0Start + x1 * 4;
                    int idx01 = sourceY1Start + x0 * 4;
                    int idx11 = sourceY1Start + x1 * 4;

                    float topB = sourcePixels[idx00] * oneMinusU + sourcePixels[idx10] * u;
                    float bottomB = sourcePixels[idx01] * oneMinusU + sourcePixels[idx11] * u;
                    byte b = (byte)(bottomB * v + topB * oneMinusV + 0.5f);

                    float topG = sourcePixels[idx00 + 1] * oneMinusU + sourcePixels[idx10 + 1] * u;
                    float bottomG = sourcePixels[idx01 + 1] * oneMinusU + sourcePixels[idx11 + 1] * u;
                    byte g = (byte)(bottomG * v + topG * oneMinusV + 0.5f);

                    float topR = sourcePixels[idx00 + 2] * oneMinusU + sourcePixels[idx10 + 2] * u;
                    float bottomR = sourcePixels[idx01 + 2] * oneMinusU + sourcePixels[idx11 + 2] * u;
                    byte r = (byte)(bottomR * v + topR * oneMinusV + 0.5f);

                    float topA = sourcePixels[idx00 + 3] * oneMinusU + sourcePixels[idx10 + 3] * u;
                    float bottomA = sourcePixels[idx01 + 3] * oneMinusU + sourcePixels[idx11 + 3] * u;
                    byte a = (byte)(bottomA * v + topA * oneMinusV + 0.5f);

                    int destIdx = destRowStart + dx * 4;
                    destPixels[destIdx] = b;
                    destPixels[destIdx + 1] = g;
                    destPixels[destIdx + 2] = r;
                    destPixels[destIdx + 3] = a;
                }
            });
        }

        // 双三次插值算法：高质量拉伸像素（速度较慢，画质最佳）
        private static void StretchPixelsBicubic(
            byte[] sourcePixels, int sourceWidth, int sourceHeight,
            byte[] destPixels, int destWidth, int destHeight)
        {
            if (sourceWidth == 0 || sourceHeight == 0 || destWidth == 0 || destHeight == 0)
                return;

            float xRatio = (float)sourceWidth / destWidth;
            float yRatio = (float)sourceHeight / destHeight;
            int sourceRowStride = sourceWidth * 4;
            int destRowStride = destWidth * 4;

            Parallel.For(0, destHeight, dy =>
            {
                float srcY = dy * yRatio;
                int yStart = (int)Math.Floor(srcY) - 1;

                for (int dx = 0; dx < destWidth; dx++)
                {
                    float srcX = dx * xRatio;
                    int xStart = (int)Math.Floor(srcX) - 1;

                    float sumB = 0f, sumG = 0f, sumR = 0f, sumA = 0f;
                    float weightSum = 0f;

                    for (int j = 0; j < 4; j++)
                    {
                        int y = yStart + j;

                        if (y < 0) y = 0;
                        else if (y >= sourceHeight) y = sourceHeight - 1;

                        int sourceYStart = y * sourceRowStride;
                        float dyDist = srcY - y;
                        float dyWeight = CubicWeight(dyDist);

                        if (dyWeight == 0f) continue;

                        for (int i = 0; i < 4; i++)
                        {
                            int x = xStart + i;

                            if (x < 0) x = 0;
                            else if (x >= sourceWidth) x = sourceWidth - 1;

                            float dxDist = srcX - x;
                            float dxWeight = CubicWeight(dxDist);

                            if (dxWeight == 0f) continue;

                            float weight = dxWeight * dyWeight;
                            weightSum += weight;

                            int sourceIndex = sourceYStart + x * 4;

                            sumB += sourcePixels[sourceIndex] * weight;
                            sumG += sourcePixels[sourceIndex + 1] * weight;
                            sumR += sourcePixels[sourceIndex + 2] * weight;
                            sumA += sourcePixels[sourceIndex + 3] * weight;
                        }
                    }

                    if (weightSum > 0f)
                    {
                        sumB /= weightSum;
                        sumG /= weightSum;
                        sumR /= weightSum;
                        sumA /= weightSum;
                    }

                    byte b = ClampToByte(sumB);
                    byte g = ClampToByte(sumG);
                    byte r = ClampToByte(sumR);
                    byte a = ClampToByte(sumA);

                    int destIndex = dy * destRowStride + dx * 4;
                    destPixels[destIndex] = b;
                    destPixels[destIndex + 1] = g;
                    destPixels[destIndex + 2] = r;
                    destPixels[destIndex + 3] = a;
                }
            });
        }

        // Lanczos插值算法：高锐度保留，抗锯齿
        private static void StretchPixelsLanczos(
            byte[] sourcePixels, int sourceWidth, int sourceHeight,
            byte[] destPixels, int destWidth, int destHeight)
        {
            StretchPixelsLanczos(sourcePixels, sourceWidth, sourceHeight, destPixels, destWidth, destHeight, 3);
        }
        private static void StretchPixelsLanczos(
            byte[] sourcePixels, int sourceWidth, int sourceHeight,
            byte[] destPixels, int destWidth, int destHeight,
            int lanczosKernelSize)
        {
            if (sourceWidth == 0 || sourceHeight == 0 || destWidth == 0 || destHeight == 0)
                return;
            if (lanczosKernelSize < 1) lanczosKernelSize = 3;

            float xRatio = (float)sourceWidth / destWidth;
            float yRatio = (float)sourceHeight / destHeight;
            int sourceRowStride = sourceWidth * 4;
            int destRowStride = destWidth * 4;
            int kernelSize = 2 * lanczosKernelSize;

            Parallel.For(0, destHeight, dy =>
            {
                float srcY = dy * yRatio;
                int yCenter = (int)Math.Floor(srcY);
                int yStart = yCenter - lanczosKernelSize + 1;

                for (int dx = 0; dx < destWidth; dx++)
                {
                    float srcX = dx * xRatio;
                    int xCenter = (int)Math.Floor(srcX);
                    int xStart = xCenter - lanczosKernelSize + 1;

                    float sumB = 0f, sumG = 0f, sumR = 0f, sumA = 0f;
                    float weightSum = 0f;

                    for (int j = 0; j < kernelSize; j++)
                    {
                        int y = yStart + j;
                        if (y < 0) y = 0;
                        else if (y >= sourceHeight) y = sourceHeight - 1;

                        int sourceYStart = y * sourceRowStride;
                        float dyDist = srcY - y;
                        float dyWeight = LanczosWeight(dyDist, lanczosKernelSize);

                        if (dyWeight <= 0f) continue;

                        for (int i = 0; i < kernelSize; i++)
                        {
                            int x = xStart + i;
                            if (x < 0) x = 0;
                            else if (x >= sourceWidth) x = sourceWidth - 1;

                            float dxDist = srcX - x;
                            float dxWeight = LanczosWeight(dxDist, lanczosKernelSize);

                            if (dxWeight <= 0f) continue;

                            float weight = dxWeight * dyWeight;
                            weightSum += weight;

                            int sourceIndex = sourceYStart + x * 4;
                            sumB += sourcePixels[sourceIndex] * weight;
                            sumG += sourcePixels[sourceIndex + 1] * weight;
                            sumR += sourcePixels[sourceIndex + 2] * weight;
                            sumA += sourcePixels[sourceIndex + 3] * weight;
                        }
                    }

                    if (weightSum > 0f)
                    {
                        sumB /= weightSum;
                        sumG /= weightSum;
                        sumR /= weightSum;
                        sumA /= weightSum;
                    }

                    byte b = ClampToByte(sumB);
                    byte g = ClampToByte(sumG);
                    byte r = ClampToByte(sumR);
                    byte a = ClampToByte(sumA);

                    int destIndex = dy * destRowStride + dx * 4;
                    destPixels[destIndex] = b;
                    destPixels[destIndex + 1] = g;
                    destPixels[destIndex + 2] = r;
                    destPixels[destIndex + 3] = a;
                }
            });
        }

        private static float CubicWeight(float x)
        {
            x = Math.Abs(x);
            if (x >= 2.0f)
                return 0.0f;
            if (x <= 1.0f)
                return 1.0f + x * x * (x - 2.0f);
            else
                return x * (x * (-x + 5.0f) - 8.0f) + 4.0f;
        }

        private static float LanczosWeight(float x, int kernelSize)
        {
            x = Math.Abs(x);
            if (x >= kernelSize) return 0f;
            if (x < float.Epsilon) return 1f;

            float piX = (float)Math.PI * x;
            return (float)(kernelSize * Math.Sin(piX) * Math.Sin(piX / kernelSize) / (piX * piX));
        }

        private static byte ClampToByte(float value)
        {
            if (value <= 0f) return 0;
            if (value >= 255f) return 255;
            return (byte)(value + 0.5f);
        }

        // 高斯模糊预处理（用于缩小图像前减少高频噪声，抗锯齿）
        private static byte[] GaussianBlur(byte[] sourcePixels, int width, int height, float sigma)
        {
            byte[] result;
            // sigma<=0无需模糊，直接返回副本
            if (sigma <= 0)
            {
                result = new byte[sourcePixels.Length];
                Array.Copy(sourcePixels, result, sourcePixels.Length);
                return result;
            }

            int kernelSize = (int)(6 * sigma) + 1;
            if (kernelSize % 2 == 0) kernelSize++;
            int halfKernel = kernelSize / 2;

            // 生成归一化高斯核
            float[] kernel = GenerateGaussianKernel(kernelSize, sigma, halfKernel);

            // 横向模糊
            byte[] temp = new byte[sourcePixels.Length];
            HorizontalBlur(sourcePixels, temp, width, height, kernel, kernelSize, halfKernel);

            // 纵向模糊
            result = new byte[sourcePixels.Length];
            VerticalBlur(temp, result, width, height, kernel, kernelSize, halfKernel);

            return result;
        }

        // 生成归一化高斯核（预计算常量减少重复运算）
        private static float[] GenerateGaussianKernel(int kernelSize, float sigma, int halfKernel)
        {
            float[] kernel = new float[kernelSize];
            float sum = 0;
            float sigmaSq2 = 2 * sigma * sigma; // 预计算2σ²，避免循环内重复计算

            for (int i = 0; i < kernelSize; i++)
            {
                float x = i - halfKernel;
                kernel[i] = (float)Math.Exp(-(x * x) / sigmaSq2);
                sum += kernel[i];
            }

            // 归一化
            for (int i = 0; i < kernelSize; i++)
            {
                kernel[i] /= sum;
            }

            return kernel;
        }

        // 横向模糊
        private static void HorizontalBlur(byte[] source, byte[] dest, int width, int height,
                                     float[] kernel, int kernelSize, int halfKernel)
        {
            int pixelStride = 4; // 每个像素4个通道（B/G/R/A）
            int rowStride = width * pixelStride; // 每行的字节数

            // 并行处理所有行
            Parallel.For(0, height, y =>
            {
                int rowStart = y * rowStride; // 当前行的起始索引（预计算，避免重复计算y*width*4）

                for (int x = 0; x < width; x++)
                {
                    // 计算核的有效范围（避免对xk做Clamp，减少条件判断）
                    int kStart = Math.Max(0, halfKernel - x); // 左边界限制：xk >= 0 → k >= halfKernel - x
                    int kEnd = Math.Min(kernelSize - 1, (width - 1 - x) + halfKernel); // 右边界限制：xk <= width-1 → k <= (width-1 -x) + halfKernel

                    // 处理每个通道
                    for (int c = 0; c < pixelStride; c++)
                    {
                        float sum = 0f;
                        for (int k = kStart; k <= kEnd; k++)
                        {
                            int xk = x + k - halfKernel; // 确保在[0, width-1]内
                            int srcIndex = rowStart + xk * pixelStride + c; // 预计算行起始，减少索引计算
                            sum += source[srcIndex] * kernel[k];
                        }

                        // 手动Clamp（替代Math.Clamp，减少函数调用）
                        byte val = sum <= 0 ? (byte)0 : (sum >= 255 ? (byte)255 : (byte)sum);
                        int destIndex = rowStart + x * pixelStride + c;
                        dest[destIndex] = val;
                    }
                }
            });
        }

        // 纵向模糊
        private static void VerticalBlur(byte[] source, byte[] dest, int width, int height,
                                       float[] kernel, int kernelSize, int halfKernel)
        {
            int pixelStride = 4;
            int rowStride = width * pixelStride;

            // 并行处理所有列
            Parallel.For(0, width, x =>
            {
                int colOffset = x * pixelStride; // 当前列的通道偏移（预计算x*4）

                for (int y = 0; y < height; y++)
                {
                    // 计算核的有效范围（避免对yk做Clamp）
                    int kStart = Math.Max(0, halfKernel - y); // 上边界限制：yk >= 0 → k >= halfKernel - y
                    int kEnd = Math.Min(kernelSize - 1, (height - 1 - y) + halfKernel); // 下边界限制：yk <= height-1 → k <= (height-1 -y) + halfKernel

                    // 处理每个通道
                    for (int c = 0; c < pixelStride; c++)
                    {
                        float sum = 0f;
                        for (int k = kStart; k <= kEnd; k++)
                        {
                            int yk = y + k - halfKernel; // 确保在[0, height-1]内
                            int srcIndex = yk * rowStride + colOffset + c; // 预计算列偏移，减少索引计算
                            sum += source[srcIndex] * kernel[k];
                        }

                        // 手动Clamp
                        byte val = sum <= 0 ? (byte)0 : (sum >= 255 ? (byte)255 : (byte)sum);
                        int destIndex = y * rowStride + colOffset + c;
                        dest[destIndex] = val;
                    }
                }
            });
        }

        // 智能补帧
        public static List<object> SmartFill(List<object> sourceFiles, int targetCount)
        {
            if (targetCount <= sourceFiles.Count)
                return sourceFiles.Take(targetCount).ToList();

            int sourceCount = sourceFiles.Count;

            // 单帧直接重复填充（例: 1→N：111...）
            if (sourceCount == 1)
            {
                return Enumerable.Repeat(sourceFiles[0], targetCount).ToList();
            }
            // 整数倍顺序循环（例: 4→8：12341234）
            else if (targetCount % sourceCount == 0)
            {
                int repeatTimes = targetCount / sourceCount;
                return Enumerable.Repeat(sourceFiles, repeatTimes).SelectMany(x => x).ToList();
            }
            else
            {
                var slowLoopUnit = SlowFill(sourceFiles, 0, sourceCount - 1);
                int slowLoopLength = slowLoopUnit.Count;

                // 慢放后循环
                if (targetCount % slowLoopLength == 0)
                {
                    int repeatTimes = targetCount / slowLoopLength;
                    return Enumerable.Repeat(slowLoopUnit, repeatTimes).SelectMany(x => x).ToList();
                }

                int quotient = targetCount / slowLoopLength;
                int remainder = targetCount % slowLoopLength;
                List<object> result = new(quotient * slowLoopLength);

                for (int i = 0; i < quotient; i++)
                {
                    result.AddRange(slowLoopUnit);
                }

                if (remainder > 0)
                {
                    // 余数为1：在末尾额外添加一个最后一帧
                    if (remainder == 1)
                    {
                        result.Add(sourceFiles.Last());
                    }
                    // 商为0且余数接近慢放单元长度：使用慢放单元的前 remainder 个
                    else if (quotient == 0 && remainder > sourceCount)
                    {
                        result.AddRange(slowLoopUnit.Take(remainder));
                    }
                    // 商为1：使用倒放补帧策略填充剩余部分
                    else if (quotient == 1)
                    {
                        int remaining = targetCount - result.Count;
                        var reversedSegment = ReverseFill(sourceFiles, remaining);
                        result.AddRange(reversedSegment);
                    }
                    // 通用情况：前N-1个慢放循环，最后一部分使用倒放补帧
                    else
                    {
                        result.RemoveRange(result.Count - slowLoopLength, slowLoopLength);

                        int remaining = targetCount - result.Count;
                        var reversedSegment = ReverseFill(sourceFiles, remaining);
                        result.AddRange(reversedSegment);
                    }
                }

                return result;
            }
        }

        private static List<object> SlowFill(List<object> sourceFiles, int startIndex, int endIndex)
        {
            var result = new List<object> { sourceFiles[startIndex] };
            for (int i = startIndex + 1; i <= endIndex; i++)
            {
                result.Add(sourceFiles[i]);
                result.Add(sourceFiles[i]);
            }
            result.RemoveAt(result.Count - 1);
            return result;
        }

        private static List<object> ReverseFill(List<object> sourceFiles, int targetCount)
        {
            if (sourceFiles.Count == 0 || targetCount <= 0) return [];
            if (targetCount <= sourceFiles.Count) return sourceFiles.Take(targetCount).ToList();

            var result = new List<object>(sourceFiles);
            if (sourceFiles.Count < 3)
            {
                result.AddRange(Enumerable.Repeat(sourceFiles.Last(), targetCount - sourceFiles.Count));
                return result;
            }

            var reversedCycle = sourceFiles.Skip(1).Take(sourceFiles.Count - 2).Reverse().ToList();
            int cyclesNeeded = (targetCount - sourceFiles.Count + reversedCycle.Count - 1) / reversedCycle.Count;

            for (int i = 0; i < cyclesNeeded; i++)
            {
                result.AddRange(reversedCycle);
            }

            return result.Take(targetCount).ToList();
        }
    }
}
